Skip to content

Conversation

@yzhou-bcom
Copy link
Contributor

No description provided.

namespace api {
namespace pipeline {

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use this syntax, otherwise doxygen does not generate the documentation properly:

/// Status of image segmentation processing
enum class ImageSegmentationStatus {
    UNINITIALIZED,    ///< processing not initialized
    INITIALIZED,      ///< processing correctly initialized, but not started
    IN_PROGRESS,      ///< processing in progress
    COMPLETED,        ///< processing completed
    ABORTED           ///< processing aborted before completion
};

If you want to test, you'll also need this change I already merged to master:
d5b6492

Without it, enum declared in undocumented namespace are simply not visible in the documentation.

* @enum class ImageSegmentationStatus
*/
enum class ImageSegmentationStatus {
UNINITIALIZED = 0, // processing not initialized
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, no need to specify each value I think, because it's probably their default value anyway.

Plus we don't really use them.

/// @brief segmentation request from an input image
/// @param[in] image pointer to image
/// @return FrameworkReturnCode::_SUCCESS (segmentation succeeded) or FrameworkReturnCode::_ERROR_ (segmentation failed)
virtual FrameworkReturnCode segmentationRequest(SRef<Image> image) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

I know it's been done elsewhere, but not a fan of this name:

  • usually a verb is used for method (action). Here it sounds like an object
  • request is redundant. If we call a method, we make a request to the object to perform an action.

It could be for example: segment(), run/performSegmentation(), or something else.

If we want to be concise, it could even be just run()-, because calling IImageSegmentationPipeline::run() it is clear enough that run() will perform an image segmentation.

Also, I'm not sure, but enum ImageSegmentationStatut could be defined inside the class, and simply be called Status. The method getStatus() is not called getImageSegmentationStatus().

Just some thoughts, you decide ;)

@@ -0,0 +1,120 @@
/**
* @copyright Copyright (c) 2017-2025 B-com http://www.b-com.com/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New file => 2025 only, no?

namespace datastructure {

/**
* @enum class Segmentation2DType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See other comment about doxygen syntaxt for enums.

return FrameworkReturnCode::_SUCCESS;
}

bool Mask2DCollection::isExistMask(uint32_t id) const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isExist is not really english. contains()?

}
};
using MaskInfoType = std::map<uint8_t, SegInfo>;
using ClassLabelType = std::map<int16_t, std::string>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this table be moved out of Mask2D? I mean, for a given segmentation process, this map is going to be the same, right ?

Or maybe not? Is this a per image thing? But in theory, it could be interesting to use a single table for all masks to not have to repeat this association int->Class in every Mask2D?

MaskInfoType is probably tied to the Mask, because being limited to 255 values, it couldn't encode a whole image sequence, so this makes more sense.

It can stay as is for now I guess, but moving it outside could be an optimization to save some memory, if need be.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the map from class to label is global. for example if the model is trained with 150 classes, it is a map(int -> string) of size 150. currently a map only has 1 mask collection. the idea was to put all segmented masks in one collection which can be a combination of several segmentation models. maybe a map should have a list of mask collections (std::vector<SRef>)


/// @brief set Id
/// @param[in] id Mask2D ID
void setId(uint32_t id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are setters useful if the object can be entirely build with its ctor?

return true;
}

SRef<const Mask2DCollection> Map::getConstMask2DCollection() const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it mandatory to return an SRef? Or a simple ref would suffice?

I.e. is there a scenario where the caller will claim the ownership of the collection, so that it can work on it while the Map is destroyed? Or is the collection lifetime linked to the one of the Map?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the mask collection's lifetime is not linked to one map. user can do getMask2DCollection(SRef& maskCollection) and continue to work on it even when the map had already been destroyed

return a simple ref is a good idea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by your comment. You say that the collection can outlive the Map, but you still agree to return a simple ref? If so, the collection cannot be processed after the Map is gone. Maybe you were describing the state as it were, and not how it was intended to be?

if (defineMaskId) {
newMask->setId(m_currentId++);
}
m_masks[newMask->getId()] = newMask;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thus do you think it's worth checking that the id does not already exist? Is it a warning or an error? Probably an error no?

/// @brief This method allow to add a Mask2D to the Mask2D manager component
/// @param[in] mask the Mask2D to add to the set of persistent Mask2Ds
/// @return FrameworkReturnCode::_SUCCESS_ if the addition succeed, else FrameworkReturnCode::_ERROR.
FrameworkReturnCode addMask(SRef<Mask2D> mask);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool defineMaskId = true parameter removed here, but not from IMapManager and IMask2DManager \ addMask(), is that intended?

Copy link
Contributor Author

@yzhou-bcom yzhou-bcom Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to simplify the id management of masks. We let the user to define the ID before adding the mask into the collection. user should do mask->setId() before adding it into the collection. Then, the maskCollection will check if a mask with the same ID exists already.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand your answer: if the user sets the ID, then we don't need the parameter. So you removed it from here, OK.
My remark was that this parameter was still present in MapManager and Mask2DManager version of addMask()

From what I see currently, MapManager passes defineId to Mask2DManager.addMask(), but then this parameter is ignored by Mask2DManager.addMask(). So maybe it needs to be removed from those classes as well?

As a side note, shouldn't the MaskCollection be responsible for managing the IDs? This way we wouldn't have to check it is valid? You could have MaskCollection::createMask2D() factory method for example.

Or having the addMask2D method return the ID the Collection have assigned to it. But the factory method would guarantee we don't expose a setId() method that allows anyone to change the ID.

Or another solution, don't put ID in Mask2D, and let the Collection manage the ID as the key of its internal map.

return m_maskInfo;
}

void Mask2D::print() const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe you could make a toString() that outputs the JSON, so you can reuse the same impl to print it here, and to output it in the file ?

return FrameworkReturnCode::_ERROR_;
}
minId = m_masks.begin()->first;
maxId = (--m_masks.end())->first;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one. I found this version for max, I'll let you pick the one you prefer (and if it works :p). There's just less syntax:
maxId = m_masks.rbegin()->first;

* * instanceId, the instance Id of the detected object, if instanceId < 0, it means that the current pixel belongs to a "stuff" class which is uncountable, otherwise it belongs to a "thing" class
* * confidence, confidence score between 0 and 1, the confidence score of the segmentation, if confidence < 0, it means that the confidence score is not available
*/
struct SegInfo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep it as is for now, this PR has to move on, but I wonder whether it could be worth introducing some kind of type hierarchy here for different type of segmentation, so that we don't have these kind of struct with fields that are sometimes irrelevant. It's probably better to have things more precisely typed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants